using CfgTable;
using IQIGame.Onigao.Framework;

namespace IQIGame.Onigao.GamePlay
{
    /// <summary>
    /// 条件模块黑板
    /// </summary>
    public class ConditionBlackboard : IReusableClass
    {
        //上下文数据
        //可用作IConditionPropFetcher实现类取值的依据，例如LevelEntity.FetchConditionProp内判断与英雄的距离时，会从黑板中获取curPlayer
        //可用作ConditionBlackboard.GetHost()获取PropFetcher的依据
        //但这些数据和Condition.csv.Type(字段类型：ConditionpParamHostType)之间没有必然联系，属于需要才加的字段，
        //例如curEntity虽然可以为Condition.csv.Type:SpecificEntity的取值提供支持，保证策划配置的entityId == 0时，可以取到当前交互的实体，
        //但当entityId != 0时，entity通过其他逻辑获取，与curEntity无关。
        //换句话说：下列字段不必与Type一一对应
        #region 上下文数据
        public IConditionPropFetcherContainer enviroment;
        public IConditionPropFetcher curPlayer;
        public IConditionPropFetcher curEntity;
        #endregion 上下文数据

        /// <summary>
        /// 对象池最大数量
        /// </summary>
        public uint MaxStore => 1;

        /// <summary>
        /// 根据Condition.csv.Type获取IConditionPropFetcher
        /// ConditionModule调用该方法，决定条件取值的目标对象
        /// </summary>
        /// <param name="hostType"></param>
        /// <param name="cfgData"></param>
        /// <returns></returns>
        public IConditionPropFetcher GetHost(ConditionPropFetcherType hostType, CfgCondition cfgData)
        {
            switch (hostType)
            {
                case ConditionPropFetcherType.Environment: //环境，只有一个
                    return enviroment;
                case ConditionPropFetcherType.CurPlayer: //当前玩家，只有一个（可通过CurPlayer获取作为Avatar的唯一英雄，也就是说获取AvatarHero数据时类型也填CurPlayer）
                    return curPlayer;
                case ConditionPropFetcherType.SpecificEntity: //指定实体，由条件配置参数指定
                    return GetEntity(cfgData);
                default: //其他玩家，非Avatar的其他英雄，道具，宠物等需要再加
                    return null;
            }
        }

        /// <summary>
        /// 获取指定实体
        /// 优先使用参数dynamicKey获取，若没有配置，则使用specificId获取
        /// </summary>
        /// <param name="dynamicKey">动态id（具体含义可参考DynCfgKey类的注释）</param>
        /// <param name="specificId">指定id</param>
        /// <returns></returns>
        private IConditionPropFetcher GetEntity(CfgCondition cfgCondition)
        {
            int entityId;
            //使用动态id
            if (!string.IsNullOrEmpty(cfgCondition.DynamicKey))
            {
                if (curEntity == null)
                {
                    LogGame.LogError("没有正在交互的实体，无法应用动态id。");
                    return null;
                }
                if (curEntity is IConditionDynCfgKeyPropFetcher dynCfgEntity)
                {
                    entityId = dynCfgEntity.GetValueFromDynCfgKey(cfgCondition.DynamicKey);
                }
                else
                {
                    LogGame.LogError($"当前实体类型[{curEntity.GetType()}]不支持动态id。");
                    return null;
                }
            }
            //使用指定id
            else
            {
                if (cfgCondition.CurValueParams == null || cfgCondition.CurValueParams.Count == 0)
                {
                    LogGame.LogError("条件判断失败，使用了实体类型，动态参数未指定，实体id也未指定。");
                    return null;
                }
                entityId = cfgCondition.CurValueParams[0];
            }
            //根据id获取实体，0代表当前实体
            if (entityId == 0)
            {
                return curEntity;
            }
            else
            {
                return enviroment.GetPropFetcherById(entityId);
            }
        }

        public void OnReset()
        {
            enviroment = null;
            curPlayer = null;
            curEntity = null;
        }
    }
}
